package com.example.gobang_system.controller;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.CircleCaptcha;
import com.example.gobang_system.common.AjaxResult;
import com.example.gobang_system.common.AppVariable;
import com.example.gobang_system.common.PasswordUtils;
import com.example.gobang_system.common.UserSessionUtils;
import com.example.gobang_system.entity.dto.UserDTO;
import com.example.gobang_system.entity.Userinfo;
import com.example.gobang_system.service.UserService;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.util.UUID;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: 86187
 * Date: 2023-05-25
 * Time: 19:37
 */
@RestController
@CrossOrigin
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;

    /**
     *  注册
     */
    @PostMapping("/reg")
    public AjaxResult reg(Userinfo userinfo) {
        // 非空校验 和 参数有效性校验
        if (userinfo == null || !StringUtils.hasLength(userinfo.getUsername()) ||
                !StringUtils.hasLength(userinfo.getPassword())) {
            // 以统一对象 AjaxResult 格式进行返回.
            return AjaxResult.fail(-1, "非法参数");
        }

        String usernameStr = "^(?![a-zA-z]+$)(?!\\d+$)(?![!@#$%^&*]+$)[a-zA-Z\\d!@#$%^&*]+$";
        String passwordStr =
                "^(?![0-9]+$)(?![a-zA-Z]+$)(?![0-9a-zA-Z]+$)(?![0-9\\W]+$)(?![a-zA-Z\\W]+$)[0-9A-Za-z\\W]{6,18}$";
        if (!userinfo.getUsername().matches(usernameStr)
            || !userinfo.getPassword().matches(passwordStr)) {
            return AjaxResult.fail(-1, "非法参数!");
        }

        // 查看用户名是否已经存在
        if (userService.getByUserName(userinfo.getUsername()) != null) {
            return AjaxResult.fail(-2, "非法请求!");
        }
//        Userinfo user = new Userinfo();
//        // 深拷贝
//        BeanUtils.copyProperties(userinfo, user);
        // 生成随机昵称
        String nickNAme = "用户" + UUID.randomUUID().toString().replace("-","").substring(0,10);
//        user.setNickname(nickNAme);
        userinfo.setNickname(nickNAme);
        // 密码加盐处理
        userinfo.setPassword(PasswordUtils.encrypt(userinfo.getPassword()));
        System.out.println(userinfo.getPassword());
        // 以统一对象 AjaxResult 格式进行返回.
        return AjaxResult.success(userService.register(userinfo));
    }

    /**
     *  登录之前添加验证码.
     */
    @GetMapping("/getcode")
    public void getCode(HttpServletRequest request, HttpServletResponse response) throws IOException {
        System.out.println("拿到验证码!");
        // 通知浏览器不要缓存
        response.setHeader("pragma", "no-cache");
        response.setHeader("cache-control", "no-cache");
        response.setHeader("expires", "0");

        // 生成一个验证码图片                                                // 宽          高   几位数的验证码     干扰点
        CircleCaptcha circleCaptcha = CaptchaUtil.createCircleCaptcha(116, 36, 4, 10);

        // 拿到图片生成的验证码
        String code = circleCaptcha.getCode();
        System.out.println("code: " + code);

        // 每调用一次此方法, 就会生成新的 code, 存到 session[redis] 中
        HttpSession session = request.getSession();
        session.setAttribute(AppVariable.LOGIN_CHECK_CODE, code);

        // 拿到流对象
        ServletOutputStream outputStream = response.getOutputStream();
        if (outputStream != null) {
            // 通过输出流输出给前端
            circleCaptcha.write(outputStream);
            // 关闭资源
            outputStream.close();
        }
    }

    /**
     *  登录
     */
    @PostMapping("/login")
    public AjaxResult login(String username, String password, String code, HttpServletRequest request) throws Exception {

        System.out.println(username + " "+ password +" "+ code);
        System.out.println(!StringUtils.hasLength(username) || !StringUtils.hasLength(password)
                || !StringUtils.hasLength(code));
        // 1. 非空校验
        if (!StringUtils.hasLength(username) || !StringUtils.hasLength(password)
                || !StringUtils.hasLength(code)) {
            return AjaxResult.fail(-1, "非法请求");
        }

        String usernameStr = "^(?![a-zA-z]+$)(?!\\d+$)(?![!@#$%^&*]+$)[a-zA-Z\\d!@#$%^&*]+$";
        String passwordStr =
                "^(?![0-9]+$)(?![a-zA-Z]+$)(?![0-9a-zA-Z]+$)(?![0-9\\W]+$)(?![a-zA-Z\\W]+$)[0-9A-Za-z\\W]{6,18}$";
        if (!username.matches(usernameStr)
                || !password.matches(passwordStr)) {
            return AjaxResult.fail(-1, "非法参数!");
        }

        // 拿到验证码 session
        String imgCode = UserSessionUtils.getImgCode(request);
        System.out.println(imgCode);
        // 验证码是否正确
        if (!code.equals(imgCode)) {
            // 验证码错误
            return AjaxResult.fail(-6,"参数验证错误");
        }
        // 2. 查询数据库
        Userinfo userinfo = userService.getByUserName(username);
        System.out.println(userinfo); // 不为空
        if (userinfo == null) {
            // 账号未注册
            return AjaxResult.fail(-7, "非法请求");
        }
        if (userinfo.getUserId() > 0) {
            if ( userinfo.getState() != 1) {
                // 账号被冻结
                return AjaxResult.fail(-2, "非法用户");
            }
            // 是有效的用户名, 接着判断密码是否正确
            if (PasswordUtils.check(password, userinfo.getPassword())) {
                // 密码正确 登录成功.
                // 拿到 session 对象.
                HttpSession session = request.getSession();
                // 将用户存储到 session 中, AppVariable.USER_SESSION_KEY 是一个全局变量
                session.setAttribute(AppVariable.USER_SESSION_KEY, userinfo);

                // 返回数据之前, 隐藏用户敏感信息(密码)
                userinfo.setPassword("");
                // 恢复 logcount 字段的默认值.
                userinfo.setLogcount(AppVariable.USER_LOGIN_COUNT);
                userService.reduceLogCount(userinfo.getLogcount(),userinfo.getUserId());

                return AjaxResult.success(userinfo);
            } else {
                // 用户名有效 但是密码不正确. logcount 要 -1
                userinfo.setLogcount(userinfo.getLogcount() - 1);
                userService.reduceLogCount(userinfo.getLogcount(),userinfo.getUserId());
                if (userinfo.getLogcount() <= 0) {
                    // 冻结账号
                    userinfo.setState(0);
                    userService.setUserState(userinfo.getState(), userinfo.getUserId());
                    return AjaxResult.fail(-1, "由于多次异常登录, 账号已被冻结!请联系管理员");
                }
                return AjaxResult.fail(-1, "登陆失败");
            }
        }
        // 走到这里 登陆失败(前端代码 data != null 才登录成功).
        return AjaxResult.fail(-1, "未知错误,登陆失败!请联系管理员");
    }


    /**
     *  查询用户信息
     */
    @RequestMapping("/showinfo")
    public AjaxResult showInfo(HttpServletRequest request) {
        // 1. 从 session中得到当前登录用户.
        Userinfo userinfo = UserSessionUtils.getUser(request);
        System.out.println(userinfo + "showinfo");
        if (userinfo == null) {
            return AjaxResult.fail(-1, "非法请求");
        }
        UserDTO userDTO = new UserDTO();
        // Spring 提供深拷贝的方式: 将 userinfo 中相同的字段拷贝到 userinfoVO.
        BeanUtils.copyProperties(userinfo, userDTO);

        return AjaxResult.success(userDTO);
    }
}
